
/***************************************************************************
 *            dc1394cam_driver.h
 * 
 *  Wed Oct 21 11:25:00 2009
 *  Copyright  2010  Michael Warren
 *  Queensland University of Technology, CyPhy Lab
 *  <michael.warren@qut.edu.au>
 ****************************************************************************/

#ifndef DC1394CAM_DRIVER_H
#define DC1394CAM_DRIVER_H

#include "config.h"

#ifdef DC1394CAM_DRIVER_OPENCV_INSTALLED
#include "highgui.h"
#endif //DC1394CAM_DRIVER_OPENCV_INSTALLED

#ifdef DC1394CAM_DRIVER_VXL_INSTALLED
#include <vxl/core/vil/vil_image_view.h>
#include <vxl/core/vil/vil_copy.h>
#endif //DC1394CAM_DRIVER_VXL_INSTALLED

#include <unistd.h>
#include <stdint.h>
#include <sys/select.h>
#include <dc1394/dc1394.h>
#include <cv.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <stdint.h>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <map>
#include <utility>
#include <string>

class camCapture
{
public:
    camCapture();
    virtual ~camCapture()
    {
        close();
    }
    // Check that camera is available on bus and claim it
    bool open(int index);
    // Open first camera found
    bool open(void)
    {
        open(0);
    }
    // Value of current frame timestamp
    uint64_t getTimeStamp(void);
    // Value of previous frame timestamp
    uint64_t getPrevTimeStamp(void);
    // Value of current frames_behind variable
    unsigned int getFramesBehind(void);
    // Cleanup memory and close firewire camera cleanly
    void close(void);
    // Dequeue a single frame from dc1394 buffer
    bool grabFrame(void);
#ifdef DC1394CAM_DRIVER_OPENCV_INSTALLED
    // Return the frame pointer to the user
    IplImage* retrieveFrame(void);
    // grabFrame and retrieveFrame in one call
    IplImage* queryFrame(void);
#endif //DC1394CAM_DRIVER_OPENCV_INSTALLED
    
#ifdef DC1394CAM_DRIVER_VXL_INSTALLED
    // Retrieve all the frames from all the cameras
    vil_image_view<vxl_byte> retrieveVxlFrames(void);
    // grabFrame and retrieveFrame in one call
    vil_image_view<vxl_byte> queryVxlFrame(void);
    // Retrieve frame from a specific camera
    vil_image_view<vxl_byte> retrieveVxlFrame(void);
#endif //DC1394CAM_DRIVER_VXL_INSTALLED
    
    /****************** Set Camera Parameters ***********************/
    // Value of open variable
    bool isOpen(void);
    // Value of started variable
    bool isStarted(void);
    // Set Firewire Mode
    bool setIsoSpeed(int speed);
    // Set frame width
    bool setWidth(int width);
    // Set frame height
    bool setHeight(int height);
    // Set frame width and height in one call
    bool setWidthAndHeight(int width, int height);
    // Set framerate
    bool setFrameRate(std::string framerate);
    // Set feature value
    bool setFeature(std::string featureString, int num);
    // Set absolute feature value
    bool setFeatureAbs(std::string featureString, float num);
    // Set feature to automatic control
    bool setFeatureAuto(std::string featureString);
    // Set feature value
    bool setPtGreyFeature(std::string featureString, int num);
    // Set absolute feature value
    bool setPtGreyFeatureAbs(std::string featureString, float num);
    // Set feature to automatic control
    bool setPtGreyFeatureAuto(std::string featureString);
    // Set number of DMA bufs
    bool setDMABufSize(int num);
    // Set cleanup
    bool setCleanup(bool value);
    // Set suppress warnings variable
    bool setSuppressWarnings(bool value);
    // Set color mode
    bool setColorMode(std::string colorMode);
    // Set guid
    bool setGUID(uint64_t value);
    
    /****************** Get Camera Parameters ***********************/ 
    // Value of index variable
    int getIndex(void);
    // Get Firewire Mode
    int getIsoSpeed(void);
    // Get frame width
    int getWidth(void);
    // Get frame height
    int getHeight(void);
    // Get framerate
    std::string getFrameRate(void);
    // Get framerate as float
    float getFrameRateFloat(void);
    // Get number of DMA bufs
    int getDMABufSize(void);
    // Get cleanup
    bool getCleanup(void);
    // Get suppress warnings variable
    bool getSuppressWarnings(void);
    // Get color mode
    std::string getColorMode(void);
    // Get GUID variable
    uint64_t getGUID(void);
    
    friend class multiCamCapture;
    
private:
    // Check config and start capturing
    bool startCapture(void);
    
    /****************** Variables ***********************/ 
    // Firewire transfer speed
    int isoSpeed;   
    // Returned frame width and height
    int frameWidth, frameHeight;
    // Desired frames per second
    std::string fps;
    // Framerate as a float
    float fps_float;
    // Number of dc1394 DMA buffers
    int nDMABufs;
    // If true, attempt cleanup of bus
    bool cleanup;
    // If set to true, frame buffer overflow warnings will be suppressed
    bool suppress_warnings;
    // GUID of camera on bus
    uint64_t guid;
    // Desired color mode
    std::string prefColorMode;
    // True if camera has been opened on firewire bus
    bool opened;
    // True if returned images are color, false if grayscale
    bool isColor;
    // dc1394 color mode
    dc1394color_coding_t colorMode;
    // True when started
    bool started;
    // Which camera on bus list
    int index;
    // Format_7
    bool format7;
    // Camera vendor id
    int cameraId;
    // dc1394 handle to camera
    dc1394camera_t* dcCam;
#ifdef DC1394CAM_DRIVER_OPENCV_INSTALLED
    // Returned image buffer
    IplImage *img;
#endif //DC1394CAM_DRIVER_OPENCV_INSTALLED
#ifdef DC1394CAM_DRIVER_VXL_INSTALLED
    // Returned image buffer
    vil_image_view<vxl_byte> vxlImg;
#endif //DC1394CAM_DRIVER_VXL_INSTALLED
    // Timestamp of current image
    uint64_t timestamp;
    uint64_t prevtimestamp;
    // Current size of buffer
    unsigned int frames_behind;
    // Temporay frame handle
    dc1394video_frame_t* frameC;
    // Vectors of features and their values/absolute values to set
    std::map<std::string,int> features_to_set;
    std::map<std::string,float> features_abs_to_set;
    std::map<std::string,int> ptgrey_features_to_set;
    std::map<std::string,float> ptgrey_features_abs_to_set;

};

class multiCamCapture
{
public:
    multiCamCapture();
    multiCamCapture(int num);
    virtual ~multiCamCapture()
    {
        close();
  	    if (debug_file.is_open())
            debug_file.close();
    }
    // How many cameras are in the multiCam Capture
    int size(void);
    // Open all cameras on bus
    bool open(void);
    // Close all open cameras on bus
    void close(void);
    // grab a frame from every camera's buffer
    bool grabFrames(void);
#ifdef DC1394CAM_DRIVER_OPENCV_INSTALLED
    // Retrieve all the frames from all the cameras
    std::vector<IplImage*> retrieveCvFrames(void);
    // grabFrame and retrieveFrame in one call
    std::vector<IplImage*> queryCvFrames(void);
    // Retrieve frame from a specific camera
    IplImage* retrieveCvFrame(int i);
#endif //DC1394CAM_DRIVER_OPENCV_INSTALLED
    
#ifdef DC1394CAM_DRIVER_VXL_INSTALLED
    // Retrieve all the frames from all the cameras
    std::vector<vil_image_view<vxl_byte> > retrieveVxlFrames(void);
    // grabFrame and retrieveFrame in one call
    std::vector<vil_image_view<vxl_byte> > queryVxlFrames(void);
    // Retrieve frame from a specific camera
    vil_image_view<vxl_byte> retrieveVxlFrame(int i);
#endif //DC1394CAM_DRIVER_VXL_INSTALLED
    
    /****************** Set Camera Parameters ***********************/
    // Set Firewire Mode
    bool setIsoSpeed(int speed);
    // Set frame width
    bool setWidth(unsigned int cam_index, int width);
    // Set frame height
    bool setHeight(unsigned int cam_index, int height);
    // Set frame width and height in one call
    bool setWidthAndHeight(unsigned int cam_index, int width, int height);
    // Set frame width for all cams
    bool setWidthAllCams(int width);
    // Set frame height for all cams
    bool setHeightAllCams(int height);
    // Set frame width and height in one call for all cams
    bool setWidthAndHeightAllCams(int width, int height);
    // Set framerate
    bool setFrameRate(std::string framerate);
    // Set feature value
    bool setFeature(unsigned int cam_index, std::string featureString, int num);
    // Set absolute feature value
    bool setFeatureAbs(unsigned int cam_index, std::string featureString, float num);
    // Set feature to auto
    bool setFeatureAuto(unsigned int cam_index, std::string featureString);
    // Set feature value for all cams
    bool setFeatureAllCams(std::string featureString, int num);
    // Set absolute feature value
    bool setFeatureAbsAllCams(std::string featureString, float num);
    // Set feature to auto
    bool setFeatureAutoAllCams(std::string featureString);
    // Set Point Grey feature value
    bool setPtGreyFeature(unsigned int cam_index, std::string featureString, int num);
    // Set Point Grey absolute feature value
    bool setPtGreyFeatureAbs(unsigned int cam_index, std::string featureString, float num);
    // Set Point Grey feature to auto
    bool setPtGreyFeatureAuto(unsigned int cam_index, std::string featureString);
    // Set Point Grey feature value for all cams
    bool setPtGreyFeatureAllCams(std::string featureString, int num);
    // Set Point Grey absolute feature value
    bool setPtGreyFeatureAbsAllCams(std::string featureString, float num);
    // Set Point Grey feature to auto
    bool setPtGreyFeatureAutoAllCams(std::string featureString);
    // Set number of DMA bufs
    bool setDMABufSize(int num);
    // Set cleanup
    bool setCleanup(bool value);
    // Set suppress warnings variable
    bool setSuppressWarnings(bool value);
    // Set color mode
    bool setColorMode(unsigned int cam_index, std::string colorMode);
    // Set color mode for all cameras
    bool setColorModeAllCams(std::string colorMode);
    // Set guid
    bool setGUID(unsigned int cam_index, uint64_t value);
    // Set debugging variable
    bool setDebug(bool value);
    
    /****************** Get Camera Parameters ***********************/ 
    // Value of open variable
    bool isOpen(void);
    // Value of started variable
    bool isStarted(void);
    // Get Firewire Mode
    int getIsoSpeed(void);
    // Get frame width
    int getWidth(unsigned int cam_index);
    // Get frame height
    int getHeight(unsigned int cam_index);
    // Get framerate
    std::string getFrameRate(void);
    // Get number of DMA bufs
    int getDMABufSize(void);
    // Get cleanup
    bool getCleanup(void);
    // Get suppress warnings variable
    bool getSuppressWarnings(void);
    // Get color mode
    std::string getColorMode(unsigned int cam_index);
    // Get GUID variable
    uint64_t getGUID(unsigned int cam_index);
    // Get debug variable;
    bool getDebug(void);
    
private:
    // Ensure that all camera dc1394 buffers are synchronised
    bool synchroniseBuffers(uint64_t last_stamp);
    // single camera captures container
    std::vector<camCapture> captures;
#ifdef DC1394CAM_DRIVER_OPENCV_INSTALLED
    // single camera frame pointer container
    std::vector<IplImage*> frames;
#endif //DC1394CAM_DRIVER_OPENCV_INSTALLED
#ifdef DC1394CAM_DRIVER_VXL_INSTALLED
    // single camera frame pointer container
    std::vector<vil_image_view<vxl_byte> > vxlFrames;
#endif //DC1394CAM_DRIVER_VXL_INSTALLED
    // True if all cameras have been started
    bool started;
    // True if all cameras have been opened;
    bool opened;
    // Suppress warnings variable
    bool suppress_warnings;
    // Log debugging information to file
    bool debug;
    // Debug output file
    std::ofstream debug_file;
};

// Check colour modes
bool isColorValid(std::string colorMode);

/****************** Register Setting Functions ***********************/
// Set a register on the camera
bool setRegister(dc1394camera_t* dcCam, uint64_t offset, uint32_t &value, uint32_t mask);

/****************** Feature Setting Functions ***********************/
// Set a feature
bool setDC1394Feature(dc1394camera_t* dcCam, dc1394feature_t feature, const char*& featureString, dc1394feature_mode_t mode, unsigned int value);
// Set a feature with absolute value
bool setDC1394FeatureAbs(dc1394camera_t* dcCam, dc1394feature_t feature, const char*& featureString, dc1394feature_mode_t mode, float value);

#endif //DC1394CAM_DRIVER_H

